home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP06.ZIP / CHAP06 / FREELOAD / DOCUMENT.CPP < prev    next >
C/C++ Source or Header  |  1993-05-21  |  17KB  |  658 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  *
  4.  * Implementation of the CFreeloaderDoc derivation of CDocument.
  5.  * We create a default handler object and use it for drawing, data
  6.  * caching, and serialization.
  7.  *
  8.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Software Design Engineer
  11.  * Microsoft Systems Developer Relations
  12.  *
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include "freeload.h"
  19.  
  20.  
  21.  
  22. /*
  23.  * CFreeloaderDoc::CFreeloaderDoc
  24.  * CFreeloaderDoc::~CFreeloaderDoc
  25.  *
  26.  * Constructor Parameters:
  27.  *  hInst           HINSTANCE of the application.
  28.  */
  29.  
  30. CFreeloaderDoc::CFreeloaderDoc(HINSTANCE hInst)
  31.     : CDocument(hInst)
  32.     {
  33.     m_pIStorage=NULL;
  34.     m_pIUnknown=NULL;
  35.     m_dwConn=0;
  36.     return;
  37.     }
  38.  
  39.  
  40. CFreeloaderDoc::~CFreeloaderDoc(void)
  41.     {
  42.     ReleaseObject();
  43.  
  44.     if (NULL!=m_pIStorage)
  45.         m_pIStorage->Release();
  46.  
  47.     return;
  48.     }
  49.  
  50.  
  51.  
  52.  
  53. /*
  54.  * CFreeloaderDoc::ReleaseObject
  55.  *
  56.  * Purpose:
  57.  *  Centralizes cleanup code for the object and its cache.
  58.  *
  59.  * Parameters:
  60.  *  None
  61.  *
  62.  * Return Value:
  63.  *  None
  64.  */
  65.  
  66. void CFreeloaderDoc::ReleaseObject(void)
  67.     {
  68.     LPOLECACHE      pIOleCache;
  69.     HRESULT         hr;
  70.  
  71.     if (0!=m_dwConn)
  72.         {
  73.         hr=m_pIUnknown->QueryInterface(IID_IOleCache
  74.             , (LPVOID FAR *)&pIOleCache);
  75.  
  76.         if (SUCCEEDED(hr))
  77.             {
  78.             pIOleCache->Uncache(m_dwConn);
  79.             pIOleCache->Release();
  80.             }
  81.         }
  82.  
  83.     if (NULL!=m_pIUnknown)
  84.         m_pIUnknown->Release();
  85.  
  86.     CoFreeUnusedLibraries();
  87.  
  88.     m_dwConn=0;
  89.     m_pIUnknown=NULL;
  90.     return;
  91.     }
  92.  
  93.  
  94.  
  95.  
  96.  
  97. /*
  98.  * CFreeloaderDoc::FMessageHook
  99.  *
  100.  * Purpose:
  101.  *  Processes WM_PAINT for the document so we can draw the object.
  102.  *
  103.  * Parameters:
  104.  *  <WndProc Parameters>
  105.  *  pLRes           LRESULT FAR * in which to store the return value
  106.  *                  for the message.
  107.  *
  108.  * Return Value:
  109.  *  BOOL            TRUE to prevent further processing, FALSE otherwise.
  110.  */
  111.  
  112. BOOL CFreeloaderDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  113.     , LPARAM lParam, LRESULT FAR *pLRes)
  114.     {
  115.     PAINTSTRUCT     ps;
  116.     HDC             hDC;
  117.     RECT            rc;
  118.     RECTL           rcl;
  119.     LPVIEWOBJECT    pIViewObject;
  120.     HRESULT         hr;
  121.  
  122.     if (WM_PAINT!=iMsg)
  123.         return FALSE;
  124.  
  125.     hDC=BeginPaint(hWnd, &ps);
  126.     GetClientRect(hWnd, &rc);
  127.  
  128.     /*
  129.      * To draw the object we can either QueryInterface for an IViewObject,
  130.      * call IViewObject::Draw, and IViewObject::Release, or we can use
  131.      * OleDraw which does exactly the same three steps, only calling
  132.      * ::Draw with defaults.  OleDraw does exactly what is done here.
  133.      */
  134.  
  135.     if (NULL!=m_pIUnknown)
  136.         {
  137.         hr=m_pIUnknown->QueryInterface(IID_IViewObject
  138.             , (LPVOID FAR *)&pIViewObject);
  139.  
  140.         if (SUCCEEDED(hr))
  141.             {
  142.            #ifndef WIN32
  143.             rcl.left  =MAKELONG(rc.left, 0);
  144.             rcl.right =MAKELONG(rc.right, 0);
  145.             rcl.top   =MAKELONG(rc.top, 0);
  146.             rcl.bottom=MAKELONG(rc.bottom, 0);
  147.            #else
  148.             //Win32 rectangles are already LONGs.
  149.             rcl=rc;
  150.            #endif
  151.  
  152.             pIViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, 0, hDC
  153.                 , &rcl, NULL, NULL, 0);
  154.             pIViewObject->Release();
  155.             }
  156.         }
  157.  
  158.     EndPaint(hWnd, &ps);
  159.  
  160.     return FALSE;
  161.     }
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169. /*
  170.  * CFreeloaderDoc::ULoad
  171.  *
  172.  * Purpose:
  173.  *  Loads a given document without any user interface overwriting the
  174.  *  previous contents of the Polyline window.  We do this by opening
  175.  *  the file and telling the Polyline to load itself from that file.
  176.  *
  177.  * Parameters:
  178.  *  fChangeFile     BOOL indicating if we're to update the window title
  179.  *                  and the filename from using this file.
  180.  *  pszFile         LPSTR to the filename to load, NULL if the file is
  181.  *                  new and untitled.
  182.  *
  183.  * Return Value:
  184.  *  UINT            An error value from DOCERR_*
  185.  */
  186.  
  187. UINT CFreeloaderDoc::ULoad(BOOL fChangeFile, LPSTR pszFile)
  188.     {
  189.     HRESULT             hr;
  190.     CLSID               clsID;
  191.     LPSTORAGE           pIStorage;
  192.     LPUNKNOWN           pIUnknown;
  193.     LPPERSISTSTORAGE    pIPersistStorage;
  194.     DWORD               dwMode=STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  195.  
  196.     if (NULL==pszFile)
  197.         {
  198.         //Create a new temp file.
  199.         hr=StgCreateDocfile(NULL, dwMode | STGM_CREATE | STGM_DELETEONRELEASE
  200.             , 0, &pIStorage);
  201.  
  202.         if (FAILED(hr))
  203.             return DOCERR_COULDNOTOPEN;
  204.  
  205.         m_pIStorage=pIStorage;
  206.  
  207.         FDirtySet(FALSE);
  208.         Rename(NULL);
  209.         return DOCERR_NONE;
  210.         }
  211.  
  212.     //Attempt to open the storage.
  213.     hr=StgOpenStorage(pszFile, NULL, dwMode, NULL, 0, &pIStorage);
  214.  
  215.     if (FAILED(hr))
  216.         return DOCERR_COULDNOTOPEN;
  217.  
  218.     /*
  219.      * When we previously called IPersistStorage::Save, OLE2.DLL kindly
  220.      * placed a CLSID into the IStorage for us, either CLSID_StaticMetafile,
  221.      * known to us as CLSID_FreeMetafile, or CLSID_StaticDib, known to us
  222.      * as CLSID_FreeDib.  All we have to do is load this CLSID,
  223.      * create the object for that ID (using CoCreateInstance, see ::FPaste
  224.      * below).
  225.      */
  226.  
  227.     hr=ReadClassStg(pIStorage, &clsID);
  228.  
  229.     //See if we know about it.
  230.     if (FAILED(hr) || !(IsEqualCLSID(clsID, CLSID_FreeMetafile)
  231.         || IsEqualCLSID(clsID, CLSID_FreeDib)))
  232.         {
  233.         pIStorage->Release();
  234.         return DOCERR_READFAILURE;
  235.         }
  236.  
  237.     //Go create an object, then tell *it* to load the data.
  238.     hr=CoCreateInstance(clsID, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown
  239.         , (LPVOID FAR *)&pIUnknown);
  240.  
  241.     if (FAILED(hr))
  242.         {
  243.         pIStorage->Release();
  244.         return DOCERR_READFAILURE;
  245.         }
  246.  
  247.     //Get IPersistStorage for the data we hold.
  248.     pIUnknown->QueryInterface(IID_IPersistStorage, (LPVOID FAR *)&pIPersistStorage);
  249.  
  250.     hr=pIPersistStorage->Load(pIStorage);
  251.     pIPersistStorage->Release();
  252.  
  253.     if (FAILED(hr))
  254.         {
  255.         pIUnknown->Release();
  256.         pIStorage->Release();
  257.         return DOCERR_READFAILURE;
  258.         }
  259.  
  260.     m_pIStorage=pIStorage;
  261.     m_pIUnknown=pIUnknown;
  262.  
  263.     Rename(pszFile);
  264.     FDirtySet(FALSE);
  265.     return DOCERR_NONE;
  266.     }
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274. /*
  275.  * CFreeloaderDoc::USave
  276.  *
  277.  * Purpose:
  278.  *  Writes the file to a known filename, requiring that the user has
  279.  *  previously used FileOpen or FileSaveAs in order to have a filename.
  280.  *
  281.  * Parameters:
  282.  *  uType           UINT indicating the type of file the user requested
  283.  *                  to save in the File Save As dialog.
  284.  *  pszFile         LPSTR under which to save.  If NULL, use the current name.
  285.  *
  286.  * Return Value:
  287.  *  UINT            An error value from DOCERR_*
  288.  */
  289.  
  290. UINT CFreeloaderDoc::USave(UINT uType, LPSTR pszFile)
  291.     {
  292.     HRESULT             hr;
  293.     LPSTORAGE           pIStorage;
  294.     LPPERSISTSTORAGE    pIPersistStorage;
  295.     CLSID               clsID;
  296.  
  297.     //If we have no data object, there's nothing to save.
  298.     if (NULL==m_pIUnknown)
  299.         return DOCERR_WRITEFAILURE;
  300.  
  301.     //Get IPersistStorage for the data we hold.
  302.     hr=m_pIUnknown->QueryInterface(IID_IPersistStorage, (LPVOID FAR *)&pIPersistStorage);
  303.  
  304.     if (FAILED(hr))
  305.         return DOCERR_WRITEFAILURE;
  306.  
  307.     //Save or Save As with the same file is just a commit.
  308.     if (NULL==pszFile || (NULL!=pszFile && 0==lstrcmpi(pszFile, m_szFile)))
  309.         {
  310.         pIPersistStorage->Save(m_pIStorage, TRUE);
  311.         m_pIStorage->Commit(STGC_ONLYIFCURRENT);
  312.  
  313.         pIPersistStorage->SaveCompleted(m_pIStorage);
  314.         pIPersistStorage->Release();
  315.  
  316.         FDirtySet(FALSE);
  317.         return DOCERR_NONE;
  318.         }
  319.  
  320.     /*
  321.      * When we're given a name, open the storage, creating it new if
  322.      * it does not exist or overwriting the old one.  Then ::CopyTo
  323.      * from the current to the new, ::Commit the new, then ::Release
  324.      * the old.